/*
 * @Author: WangTao borderpanda@163.com
 * @Date: 2025-09-04 22:09:31
 * @LastEditors: WangTao borderpanda@163.com
 * @LastEditTime: 2025-09-04 22:33:26
 * @Description:
 */
import {
  Viewer,
  EllipsoidTerrainProvider,
  CesiumTerrainProvider,
  CallbackProperty,
  HeightReference,
  ImageryLayer,
  Resource,
  WebMapTileServiceImageryProvider,
  Cartesian2,
  Cartesian3,
  Cartographic,
  defined,
  Ellipsoid,
  Ray,
  Math as CesiumMath,
} from "joCesium";
import { cacheUrl, tk, subdomains } from "./CesiumViewer";

// 天地图注记
export const addTdtCia = (viewer) => {
  const isIOS = window.navigator.appVersion.includes("iPhone");
  const proxy = Proxy;
  // @ts-ignore
  proxy.getURL = (resource: string) =>
    resource.replaceAll("http%3A%2F%2F", "http://").replaceAll("%3A", ":");
  const CiaProvider = new WebMapTileServiceImageryProvider({
    // url:
    //   "http://{s}.tianditu.com/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg&tk=" +
    //   tk,
    url: isIOS
      ? "http://{s}.tianditu.com/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg&tk=" +
        tk
      : new Resource({
          url: `{s}/cacheServer/api.tdtmap.com/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${tk}`,
          // @ts-ignore
          proxy,
        }),
    layer: "tdtCiaLayer",
    style: "default",
    format: "image/jpeg",
    // subdomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
    subdomains: isIOS
      ? ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"]
      : subdomains,
    tileMatrixSetID: "GoogleMapsCompatible",
    minimumLevel: 0, // 最小层级
    maximumLevel: 18, // 最大层级
  });
  const ciaLayer = new ImageryLayer(CiaProvider, {});
  viewer.imageryLayers.add(ciaLayer);
  return ciaLayer;
};

/**
 * 获取地形高度引用
 * @param viewer
 * @returns
 */
export const getHeightReference = (viewer: Viewer) => {
  return new CallbackProperty(() => {
    return viewer.scene.mode === 3
      ? HeightReference.CLAMP_TO_GROUND
      : HeightReference.NONE;
  }, false);
};

/**
 * 是否显示地形
 * @param {*} viewer
 */
export const toggleTerrain = async (viewer: Viewer, isShowTerrain: boolean) => {
  const { scene } = viewer;
  let terrainProvider: EllipsoidTerrainProvider | CesiumTerrainProvider;
  if (!isShowTerrain) {
    terrainProvider = new EllipsoidTerrainProvider({});
  } else {
    terrainProvider = await CesiumTerrainProvider.fromUrl(
      `${cacheUrl}/cacheServer/assets.cesium.com/1`
    );
  }
  scene.terrainProvider = terrainProvider;
};

// 不同场景下的世界坐标
export const getCartesian = (
  position: Cartesian2,
  viewer: Viewer
): Cartesian3 => {
  const mapScene = viewer.scene;
  let cartesian;
  // 在模型上获取点击对象
  const pickedObject = mapScene.pick(position);
  if (defined(pickedObject) && mapScene.pickPositionSupported) {
    // 取得点击的空间坐标
    cartesian = mapScene.pickPosition(position);

    if (cartesian) {
      // 根据坐标系标准，将笛卡尔坐标转换为地理坐标,cartographic单位:弧度
      const cartographic = Cartographic.fromCartesian(cartesian);
      if (cartographic.height < 0) {
        const ray = viewer.camera.getPickRay(position);
        // 在地形上重新获取坐标
        cartesian = mapScene.globe.pick(ray as Ray, mapScene);
      }
    }
  }
  // 在地形上
  if (!defined(cartesian)) {
    const ray = viewer.camera.getPickRay(position);
    cartesian = mapScene.globe.pick(ray as Ray, mapScene);
  }

  // 在椭球体上
  if (!defined(cartesian)) {
    cartesian = mapScene.camera.pickEllipsoid(
      position,
      mapScene.globe.ellipsoid
    );
  }
  return cartesian;
};

/**
 * 笛卡尔坐标转经纬度
 * @param cartesian Cartesian3
 * @returns {Object} { x, y, z }
 */
export const transformCartesianToWGS84 = (cartesian: Cartesian3) => {
  const ellipsoid = Ellipsoid.WGS84;
  const cartographic = ellipsoid.cartesianToCartographic(cartesian);
  const x: number = CesiumMath.toDegrees(cartographic.longitude);
  const y: number = CesiumMath.toDegrees(cartographic.latitude);
  const z: number = cartographic.height;
  return { x, y, z };
};
